package com.yfht.framework.base.dao.impl;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import com.yfht.framework.base.dao.IMultiDAO;

@Repository("multiDao")
public class MultiDAOImpl implements IMultiDAO{
	 protected final Log logger = LogFactory.getLog(getClass());

	  @Resource
	  private SessionFactory sessionFactory;

	  @Resource
	  private DataSource dataSource;

	  @Resource
	  private JdbcTemplate jdbcTemplate;
	  private SqlMapClientTemplate sqlMapClientTemplate;
	  private HibernateTemplate hibernateTemplate;
	@Override
	public Connection getConnection() {
		// TODO Auto-generated method stub
		 Connection rs = null;
	    try {
	      rs = this.dataSource.getConnection();
	    } catch (SQLException se) {
	      throw new RuntimeException(se);
	    }
		return rs;
	}

	@Override
	public JdbcTemplate getJdbcTemplate() {
		// TODO Auto-generated method stub
		 if (this.jdbcTemplate == null){
			 this.jdbcTemplate = new JdbcTemplate(this.dataSource);
	     }
		 return this.jdbcTemplate;
	}

	@Override
	public HibernateTemplate getHibernateTemplate() {
		// TODO Auto-generated method stub
		  if (this.hibernateTemplate == null){
		      this.hibernateTemplate = new HibernateTemplate(this.sessionFactory);
		  }
		  return this.hibernateTemplate;
	}

	@Override
	public SqlMapClientTemplate getSqlMapClientTemplate() {
		// TODO Auto-generated method stub
		return null;
	}

	/**load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常,查找缓存,用代理机制**/
	@Override
	public Object findByID_Hibernate_Load(Class clazz, Serializable ID) {
		// TODO Auto-generated method stub
		if(ID == null){
			return null;
		}else{
			return getHibernateTemplate().load(clazz, ID);
		}
	}

	@Override
	/**get方法检索不到的话会返回null**/
	public Object findByID_Hibernate_Get(Class clazz, Serializable ID) {
		// TODO Auto-generated method stub
		if(ID == null){
			return null;
		}else{
			return getHibernateTemplate().get(clazz, ID);
		}
	}

	@Override
	public Object findByID_Hibernate_NamedQuery(String queryID, Serializable ID) {
		// TODO Auto-generated method stub
		List list = getHibernateTemplate().findByNamedQuery(queryID, ID);
	    Iterator it = list.iterator();
	    Object vo = null;
	    if (it.hasNext()) {
	      vo = it.next();
	    }

	    return vo;
	}

	@Override
	public List findAll_Hibernate_Object(Class clazz) {
		// TODO Auto-generated method stub
		return getHibernateTemplate().loadAll(clazz);
	}

	@Override
	public List findByHQL_Hibernate(String hql) {
		// TODO Auto-generated method stub
		
		return getHibernateTemplate().find(hql);
		
	}
	public List findByHQL_Hibernate(String hql,Object...param){
		return getHibernateTemplate().find(hql,param);
	}
	
	@Override
	public List findByExample_Hibernate(Object exampleObj) {
		// TODO Auto-generated method stub
		return getHibernateTemplate().findByExample(exampleObj);
	}

	@Override
	public List findByExample_Hibernate(Object exampleObj, int startIndex,int maxResults) {
		// TODO Auto-generated method stub
		return getHibernateTemplate().findByExample(exampleObj, startIndex, maxResults);
	}

	@Override
	public List findByHQL_Hibernate(String hql, int startIndex, int maxResults) {
		// TODO Auto-generated method stub
		return getHibernateTemplate().find(hql, startIndex, maxResults);
	}

	//need test
	@Override
	public List findByHQL_Hibernate(final String hql, final int startIndex, final int maxResults,final Object... paramArrayOfObject) {
		// TODO Auto-generated method stub
		return getHibernateTemplate().executeFind(new HibernateCallback(){
			 public Object doInHibernate(Session session ) throws HibernateException, SQLException {   
	                Query query=session.createQuery(hql);   
	                query.setFirstResult(startIndex);   
	                query.setMaxResults(maxResults);  
	                for(int i = 0 ; i < paramArrayOfObject.length; i++){
	                	   query.setParameter(i, paramArrayOfObject[i]);
	                }
	                return query.list();   
	            }   
		});
	}

	@Override
	public void save_Hibernate_Object(Object object) {
		// TODO Auto-generated method stub
		this.getHibernateTemplate().save(object);
	}

	@Override
	public void update_Hibernate_Object(Object object) {
		// TODO Auto-generated method stub
		this.getHibernateTemplate().update(object);
		
	}

	@Override
	public void delete_Hibernate_Object(Object object) {
		// TODO Auto-generated method stub
		this.getHibernateTemplate().delete(object);
	}

	@Override
	public void deleteByID_Hibernate_Object(Class clazz, Serializable ID) {
		// TODO Auto-generated method stub
		 Object entity = this.getHibernateTemplate().get(clazz, ID);
		 this.delete_Hibernate_Object(entity);
	}

	@Override
	public void bulkUpdate(String hql) {
		// TODO Auto-generated method stub
		getHibernateTemplate().bulkUpdate(hql);
	}

	@Override
	public void bulkUpdate(String hql, Object paramObject) {
		// TODO Auto-generated method stub
		getHibernateTemplate().bulkUpdate(hql,paramObject);
	}

	@Override
	public void bulkUpdate(String hql, Object[] paramArrayOfObject) {
		// TODO Auto-generated method stub
		getHibernateTemplate().bulkUpdate(hql,paramArrayOfObject);
	}

	@Override
	public void delete_JDBC(String sql) {
		// TODO Auto-generated method stub
		 getJdbcTemplate().execute(sql);
	}

	@Override
	public void update_JDBC(String sql) {
		// TODO Auto-generated method stub
		getJdbcTemplate().execute(sql);
	}

	@Override
	public List findAll_JDBC(String sql) {
		// TODO Auto-generated method stub
		return getJdbcTemplate().queryForList(sql);
	}
	
	@Override
	public List findAll_JDBC(String sql, Object... param){
		return getJdbcTemplate().queryForList(sql, param);
	}
	
	@Override
	public String formateCountHQL(String hql){
		Assert.hasText(hql);
		return "select count(*) " + removeSelect(removeOrders(hql));
	}
	
	private static String removeOrders(String hql){
		Assert.hasText(hql);
		Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(hql);
		StringBuffer sb = new StringBuffer();
		while(m.find()){
			m.appendReplacement(sb, "");
		}
		m.appendTail(sb);
		return sb.toString();
	}
	
	private static String removeSelect(String hql){
		Assert.hasText(hql);
		int beginPos = hql.toLowerCase().indexOf("from");
		Assert.isTrue(beginPos!=-1,"hql: "+hql+" must has a keyword from");
		return hql.substring(beginPos);
	}
}
